# Copyright 2024 Bloomberg Finance L.P.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Additional data for metrics-related integration tests.

Note: currently these tests are placed in 'test_admin_client.py' tests block, but
      might be moved to their separate source file if we add more of them.

Note: when the metrics collection evolves, it might be necessary to update
      the data structures in this source. To do so, it's possible to copy values
      observed in the debugger for the specific test and paste them as a dictionary,
      while replacing non-fixed parameters such as time intervals with a
      condition placeholders (see 'GreaterThan').
"""

from typing import Any, Dict


class ValueConstraint:
    """The base class for non-fixed values in a data."""

    def check(self, value: Any) -> bool:
        """Return 'True' if the specified 'value' satisfy the checked constraint.
        The caller is responsible for deciding what to do next, e.g. raising an assert.
        """
        ...


class AnyValue(ValueConstraint):
    """This constraint allows any value."""

    def __init__(self) -> None:
        pass

    def check(self, value: Any) -> bool:
        """Always pass the check."""
        return True


class GreaterThan(ValueConstraint):
    """This constraint checks if the provided value is greater than the set constraint."""

    def __init__(self, constraint: Any) -> None:
        self._constraint = constraint

    def check(self, value: Any) -> bool:
        """Check if the specified 'value' is greater than the stored '_constraint'."""
        return self._constraint <= value


def _deep_merge(d1: Dict[Any, Any], d2: Dict[Any, Any]) -> Dict[Any, Any]:
    """%sMerge 2 dictionaries recursively"""

    assert isinstance(d1, dict)
    assert isinstance(d2, dict)

    copy = dict(d1)
    for key, val in d2.items():
        if isinstance(copy[key], dict) and isinstance(val, dict):
            copy[key] = _deep_merge(copy[key], val)
        else:
            # key is not in copy/d1 or there is a type mismatch
            copy[key] = val
    return copy


TEST_QUEUE_STATS_EMPTY = {
    "appIds": {
        "bar": {
            "values": {
                "queue_ack_msgs": 0,
                "queue_ack_msgs_abs": 0,
                "queue_ack_time_avg": 0,
                "queue_ack_time_max": 0,
                "queue_bytes_current": 0,
                "queue_bytes_utilization_max": 0,
                "queue_cfg_bytes": 0,
                "queue_cfg_msgs": 0,
                "queue_confirm_msgs": 0,
                "queue_confirm_msgs_abs": 0,
                "queue_confirm_time_avg": 0,
                "queue_confirm_time_max": 0,
                "queue_consumers_count": 0,
                "queue_content_bytes": 0,
                "queue_content_msgs": 0,
                "queue_gc_msgs": 0,
                "queue_gc_msgs_abs": 0,
                "queue_history_abs": 0,
                "queue_msgs_current": 0,
                "queue_msgs_utilization_max": 0,
                "queue_nack_msgs": 0,
                "queue_nack_msgs_abs": 0,
                "queue_nack_noquorum_msgs": 0,
                "queue_nack_noquorum_msgs_abs": 0,
                "queue_producers_count": 0,
                "queue_push_bytes": 0,
                "queue_push_bytes_abs": 0,
                "queue_push_msgs": 0,
                "queue_push_msgs_abs": 0,
                "queue_put_bytes": 0,
                "queue_put_bytes_abs": 0,
                "queue_put_msgs": 0,
                "queue_put_msgs_abs": 0,
                "queue_queue_time_avg": 0,
                "queue_queue_time_max": 0,
                "queue_reject_msgs": 0,
                "queue_reject_msgs_abs": 0,
                "queue_role": 0,
            }
        },
        "baz": {
            "values": {
                "queue_ack_msgs": 0,
                "queue_ack_msgs_abs": 0,
                "queue_ack_time_avg": 0,
                "queue_ack_time_max": 0,
                "queue_bytes_current": 0,
                "queue_bytes_utilization_max": 0,
                "queue_cfg_bytes": 0,
                "queue_cfg_msgs": 0,
                "queue_confirm_msgs": 0,
                "queue_confirm_msgs_abs": 0,
                "queue_confirm_time_avg": 0,
                "queue_confirm_time_max": 0,
                "queue_consumers_count": 0,
                "queue_content_bytes": 0,
                "queue_content_msgs": 0,
                "queue_gc_msgs": 0,
                "queue_gc_msgs_abs": 0,
                "queue_history_abs": 0,
                "queue_msgs_current": 0,
                "queue_msgs_utilization_max": 0,
                "queue_nack_msgs": 0,
                "queue_nack_msgs_abs": 0,
                "queue_nack_noquorum_msgs": 0,
                "queue_nack_noquorum_msgs_abs": 0,
                "queue_producers_count": 0,
                "queue_push_bytes": 0,
                "queue_push_bytes_abs": 0,
                "queue_push_msgs": 0,
                "queue_push_msgs_abs": 0,
                "queue_put_bytes": 0,
                "queue_put_bytes_abs": 0,
                "queue_put_msgs": 0,
                "queue_put_msgs_abs": 0,
                "queue_queue_time_avg": 0,
                "queue_queue_time_max": 0,
                "queue_reject_msgs": 0,
                "queue_reject_msgs_abs": 0,
                "queue_role": 0,
            }
        },
        "foo": {
            "values": {
                "queue_ack_msgs": 0,
                "queue_ack_msgs_abs": 0,
                "queue_ack_time_avg": 0,
                "queue_ack_time_max": 0,
                "queue_bytes_current": 0,
                "queue_bytes_utilization_max": 0,
                "queue_cfg_bytes": 0,
                "queue_cfg_msgs": 0,
                "queue_confirm_msgs": 0,
                "queue_confirm_msgs_abs": 0,
                "queue_confirm_time_avg": 0,
                "queue_confirm_time_max": 0,
                "queue_consumers_count": 0,
                "queue_content_bytes": 0,
                "queue_content_msgs": 0,
                "queue_gc_msgs": 0,
                "queue_gc_msgs_abs": 0,
                "queue_history_abs": 0,
                "queue_msgs_current": 0,
                "queue_msgs_utilization_max": 0,
                "queue_nack_msgs": 0,
                "queue_nack_msgs_abs": 0,
                "queue_nack_noquorum_msgs": 0,
                "queue_nack_noquorum_msgs_abs": 0,
                "queue_producers_count": 0,
                "queue_push_bytes": 0,
                "queue_push_bytes_abs": 0,
                "queue_push_msgs": 0,
                "queue_push_msgs_abs": 0,
                "queue_put_bytes": 0,
                "queue_put_bytes_abs": 0,
                "queue_put_msgs": 0,
                "queue_put_msgs_abs": 0,
                "queue_queue_time_avg": 0,
                "queue_queue_time_max": 0,
                "queue_reject_msgs": 0,
                "queue_reject_msgs_abs": 0,
                "queue_role": 0,
            }
        },
    },
    "values": {
        "queue_ack_msgs": 0,
        "queue_ack_msgs_abs": 0,
        "queue_ack_time_avg": 0,
        "queue_ack_time_max": 0,
        "queue_bytes_current": 0,
        "queue_bytes_utilization_max": 0,
        "queue_cfg_bytes": 0,
        "queue_cfg_msgs": 0,
        "queue_confirm_msgs": 0,
        "queue_confirm_msgs_abs": 0,
        "queue_confirm_time_avg": 0,
        "queue_confirm_time_max": 0,
        "queue_consumers_count": 0,
        "queue_content_bytes": 0,
        "queue_content_msgs": 0,
        "queue_gc_msgs": 0,
        "queue_gc_msgs_abs": 0,
        "queue_history_abs": 0,
        "queue_msgs_current": 0,
        "queue_msgs_utilization_max": 0,
        "queue_nack_msgs": 0,
        "queue_nack_msgs_abs": 0,
        "queue_nack_noquorum_msgs": 0,
        "queue_nack_noquorum_msgs_abs": 0,
        "queue_producers_count": 0,
        "queue_push_bytes": 0,
        "queue_push_bytes_abs": 0,
        "queue_push_msgs": 0,
        "queue_push_msgs_abs": 0,
        "queue_put_bytes": 0,
        "queue_put_bytes_abs": 0,
        "queue_put_msgs": 0,
        "queue_put_msgs_abs": 0,
        "queue_queue_time_avg": 0,
        "queue_queue_time_max": 0,
        "queue_reject_msgs": 0,
        "queue_reject_msgs_abs": 0,
        "queue_role": 0,
    },
}

TEST_QUEUE_STATS_AFTER_POST = _deep_merge(
    TEST_QUEUE_STATS_EMPTY,
    {
        "appIds": {
            "bar": {
                "values": {
                    "queue_bytes_current": 96,
                    "queue_content_bytes": 96,
                    "queue_content_msgs": 32,
                    "queue_msgs_current": 32,
                }
            },
            "baz": {
                "values": {
                    "queue_bytes_current": 96,
                    "queue_content_bytes": 96,
                    "queue_content_msgs": 32,
                    "queue_msgs_current": 32,
                }
            },
            "foo": {
                "values": {
                    "queue_bytes_current": 96,
                    "queue_content_bytes": 96,
                    "queue_content_msgs": 32,
                    "queue_msgs_current": 32,
                }
            },
        },
        "values": {
            "queue_ack_msgs": GreaterThan(0),
            "queue_ack_msgs_abs": 32,
            "queue_ack_time_avg": GreaterThan(0),
            "queue_ack_time_max": GreaterThan(0),
            "queue_bytes_current": 96,
            "queue_cfg_bytes": 1048576,
            "queue_cfg_msgs": 1000,
            "queue_content_bytes": 96,
            "queue_content_msgs": 32,
            "queue_msgs_current": 32,
            "queue_msgs_utilization_max": 3,
            "queue_put_bytes": GreaterThan(0),
            "queue_put_bytes_abs": 96,
            "queue_put_msgs": GreaterThan(0),
            "queue_put_msgs_abs": 32,
            "queue_role": 1,
        },
    },
)

TEST_QUEUE_STATS_AFTER_CONFIRM_SINGLE_NODE = _deep_merge(
    TEST_QUEUE_STATS_EMPTY,
    {
        "appIds": {
            "bar": {
                "values": {
                    "queue_bytes_current": 30,
                    "queue_confirm_time_avg": GreaterThan(0),
                    "queue_confirm_time_max": GreaterThan(0),
                    "queue_content_bytes": 96,
                    "queue_content_msgs": 32,
                    "queue_msgs_current": 10,
                    "queue_queue_time_avg": GreaterThan(0),
                    "queue_queue_time_max": GreaterThan(0),
                }
            },
            "baz": {
                "values": {
                    "queue_bytes_current": 63,
                    "queue_confirm_time_avg": GreaterThan(0),
                    "queue_confirm_time_max": GreaterThan(0),
                    "queue_content_bytes": 96,
                    "queue_content_msgs": 32,
                    "queue_msgs_current": 21,
                    "queue_queue_time_avg": GreaterThan(0),
                    "queue_queue_time_max": GreaterThan(0),
                }
            },
            "foo": {
                "values": {
                    "queue_bytes_current": 0,
                    "queue_confirm_time_avg": GreaterThan(0),
                    "queue_confirm_time_max": GreaterThan(0),
                    "queue_content_bytes": 96,
                    "queue_content_msgs": 32,
                    "queue_msgs_current": 0,
                    "queue_queue_time_avg": GreaterThan(0),
                    "queue_queue_time_max": GreaterThan(0),
                }
            },
        },
        "values": {
            "queue_ack_msgs": 32,
            "queue_ack_msgs_abs": 32,
            "queue_ack_time_avg": GreaterThan(0),
            "queue_ack_time_max": GreaterThan(0),
            "queue_bytes_current": 63,
            "queue_cfg_bytes": 1048576,
            "queue_cfg_msgs": 1000,
            "queue_confirm_msgs": 65,
            "queue_confirm_msgs_abs": 65,
            "queue_confirm_time_avg": GreaterThan(0),
            "queue_confirm_time_max": GreaterThan(0),
            "queue_consumers_count": 3,
            "queue_content_bytes": 96,
            "queue_content_msgs": 32,
            "queue_history_abs": 11,
            "queue_msgs_current": 21,
            "queue_msgs_utilization_max": 3,
            "queue_push_bytes": 288,
            "queue_push_bytes_abs": 288,
            "queue_push_msgs": 96,
            "queue_push_msgs_abs": 96,
            "queue_put_bytes": 96,
            "queue_put_bytes_abs": 96,
            "queue_put_msgs": 32,
            "queue_put_msgs_abs": 32,
            "queue_queue_time_avg": GreaterThan(0),
            "queue_queue_time_max": GreaterThan(0),
            "queue_role": 1,
        },
    },
)

TEST_QUEUE_STATS_AFTER_CONFIRM_MULTI_NODE = _deep_merge(
    TEST_QUEUE_STATS_EMPTY,
    {
        "appIds": {
            "bar": {
                "values": {
                    "queue_bytes_current": 30,
                    "queue_content_bytes": 96,
                    "queue_content_msgs": 32,
                    "queue_msgs_current": 10,
                    "queue_queue_time_avg": GreaterThan(0),
                    "queue_queue_time_max": GreaterThan(0),
                }
            },
            "baz": {
                "values": {
                    "queue_bytes_current": 63,
                    "queue_content_bytes": 96,
                    "queue_content_msgs": 32,
                    "queue_msgs_current": 21,
                    "queue_queue_time_avg": GreaterThan(0),
                    "queue_queue_time_max": GreaterThan(0),
                }
            },
            "foo": {
                "values": {
                    "queue_bytes_current": 0,
                    "queue_content_bytes": 96,
                    "queue_content_msgs": 32,
                    "queue_msgs_current": 0,
                    "queue_queue_time_avg": GreaterThan(0),
                    "queue_queue_time_max": GreaterThan(0),
                }
            },
        },
        "values": {
            "queue_bytes_current": 63,
            "queue_cfg_bytes": 1048576,
            "queue_cfg_msgs": 1000,
            "queue_consumers_count": 3,
            "queue_content_bytes": 96,
            "queue_content_msgs": 32,
            "queue_history_abs": 11,
            "queue_msgs_current": 21,
            "queue_msgs_utilization_max": 3,
            "queue_push_bytes": AnyValue(),
            "queue_push_bytes_abs": AnyValue(),
            "queue_push_msgs": AnyValue(),
            "queue_push_msgs_abs": AnyValue(),
            "queue_queue_time_avg": GreaterThan(0),
            "queue_queue_time_max": GreaterThan(0),
            "queue_role": 1,
        },
    },
)

TEST_QUEUE_STATS_AFTER_PURGE_SINGLE_NODE = _deep_merge(
    TEST_QUEUE_STATS_EMPTY,
    {
        "appIds": {
            "bar": {
                "values": {
                    "queue_bytes_current": 30,
                    "queue_confirm_time_avg": GreaterThan(0),
                    "queue_confirm_time_max": GreaterThan(0),
                    "queue_content_bytes": 96,
                    "queue_content_msgs": 32,
                    "queue_msgs_current": 10,
                    "queue_queue_time_avg": GreaterThan(0),
                    "queue_queue_time_max": GreaterThan(0),
                }
            },
            "baz": {
                "values": {
                    "queue_bytes_current": 0,
                    "queue_confirm_time_avg": GreaterThan(0),
                    "queue_confirm_time_max": GreaterThan(0),
                    "queue_content_bytes": 96,
                    "queue_content_msgs": 32,
                    "queue_msgs_current": 0,
                    "queue_queue_time_avg": GreaterThan(0),
                    "queue_queue_time_max": GreaterThan(0),
                }
            },
            "foo": {
                "values": {
                    "queue_bytes_current": 0,
                    "queue_confirm_time_avg": GreaterThan(0),
                    "queue_confirm_time_max": GreaterThan(0),
                    "queue_content_bytes": 96,
                    "queue_content_msgs": 32,
                    "queue_msgs_current": 0,
                    "queue_queue_time_avg": GreaterThan(0),
                    "queue_queue_time_max": GreaterThan(0),
                }
            },
        },
        "values": {
            "queue_ack_msgs": 32,
            "queue_ack_msgs_abs": 32,
            "queue_ack_time_avg": GreaterThan(0),
            "queue_ack_time_max": GreaterThan(0),
            "queue_bytes_current": 30,
            "queue_cfg_bytes": 1048576,
            "queue_cfg_msgs": 1000,
            "queue_confirm_msgs": 65,
            "queue_confirm_msgs_abs": 65,
            "queue_confirm_time_avg": GreaterThan(0),
            "queue_confirm_time_max": GreaterThan(0),
            "queue_consumers_count": 3,
            "queue_content_bytes": 96,
            "queue_content_msgs": 32,
            "queue_history_abs": 22,
            "queue_msgs_current": 10,
            "queue_msgs_utilization_max": 3,
            "queue_push_bytes": 288,
            "queue_push_bytes_abs": 288,
            "queue_push_msgs": 96,
            "queue_push_msgs_abs": 96,
            "queue_put_bytes": 96,
            "queue_put_bytes_abs": 96,
            "queue_put_msgs": 32,
            "queue_put_msgs_abs": 32,
            "queue_queue_time_avg": GreaterThan(0),
            "queue_queue_time_max": GreaterThan(0),
            "queue_role": 1,
        },
    },
)

TEST_QUEUE_STATS_AFTER_PURGE_MULTI_NODE = _deep_merge(
    TEST_QUEUE_STATS_EMPTY,
    {
        "appIds": {
            "bar": {
                "values": {
                    "queue_bytes_current": 30,
                    "queue_content_bytes": 96,
                    "queue_content_msgs": 32,
                    "queue_msgs_current": 10,
                    "queue_queue_time_avg": GreaterThan(0),
                    "queue_queue_time_max": GreaterThan(0),
                }
            },
            "baz": {
                "values": {
                    "queue_bytes_current": 0,
                    "queue_content_bytes": 96,
                    "queue_content_msgs": 32,
                    "queue_msgs_current": 0,
                    "queue_queue_time_avg": GreaterThan(0),
                    "queue_queue_time_max": GreaterThan(0),
                }
            },
            "foo": {
                "values": {
                    "queue_bytes_current": 0,
                    "queue_content_bytes": 96,
                    "queue_content_msgs": 32,
                    "queue_msgs_current": 0,
                    "queue_queue_time_avg": GreaterThan(0),
                    "queue_queue_time_max": GreaterThan(0),
                }
            },
        },
        "values": {
            "queue_bytes_current": 30,
            "queue_cfg_bytes": 1048576,
            "queue_cfg_msgs": 1000,
            "queue_consumers_count": 3,
            "queue_content_bytes": 96,
            "queue_content_msgs": 32,
            "queue_history_abs": 22,
            "queue_msgs_current": 10,
            "queue_msgs_utilization_max": 3,
            "queue_push_bytes": 93,
            "queue_push_bytes_abs": 93,
            "queue_push_msgs": 31,
            "queue_push_msgs_abs": 31,
            "queue_queue_time_avg": GreaterThan(0),
            "queue_queue_time_max": GreaterThan(0),
            "queue_role": 1,
        },
    },
)

TEST_QUEUE_STATS_TOO_OFTEN_SNAPSHOTS = {
    "error": {
        "message": "Cannot save the recent snapshot, trying to make snapshots too often"
    }
}
